import socket
from transmission_rpc import Client as TransmissionClient, TransmissionError


class TransmissionManager:
    """Transmission下载客户端管理器，提供连接、获取下载列表和添加种子等功能"""
    
    # 状态码到文本描述的映射，使用类变量提高复用性
    _STATUS_MAP = {
        0: '停止',
        1: '等待检查',
        2: '检查中',
        3: '等待下载',
        4: '下载中',
        5: '等待上传',
        6: '上传中',
        7: '种子排队中',
        8: '已暂停'
    }

    def __init__(self, config):
        """
        初始化Transmission管理器
        
        :param config: 连接配置，应包含host、port、username、password等键
        """
        self.config = config
        self.client = None
        self.last_error = None  # 用于存储最后发生的错误信息
        
        # 确保配置项存在
        if 'host' not in self.config:
            self.config['host'] = 'localhost'
        if 'port' not in self.config:
            self.config['port'] = 9091
        if 'username' not in self.config:
            self.config['username'] = ''
        if 'password' not in self.config:
            self.config['password'] = ''
            
    def test_connection(self):
        """
        使用Socket测试服务器连接性（仅检查端口可达性）
        
        :return: 连接成功返回True，否则返回False
        """
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.settimeout(10)
                host = self.config.get('host', 'localhost')
                port = int(self.config.get('port', 9091))
                result = s.connect_ex((host, port))
                return result == 0
        except Exception as e:
            self.last_error = f"连接测试失败: {str(e)}"
            return False
            
    def connect(self):
        """
        连接到Transmission服务
        
        :return: 连接成功返回True，否则返回False
        """
        self.last_error = None
        if self.client:
            return True  # 已连接状态直接返回成功
            
        try:
            host = self.config.get('host', 'localhost')
            port = self.config.get('port', 9091)
            
            self.client = TransmissionClient(
                host=host,
                port=port,
                username=self.config.get('username', ''),
                password=self.config.get('password', '')
            )
            
            return True
        except TransmissionError as e:
            self.last_error = f"Transmission连接失败: {str(e)}"
        except Exception as e:
            self.last_error = f"连接过程发生未知错误: {str(e)}"
            
        self.client = None
        return False
    
    def get_downloads(self):
        """
        获取当前所有下载任务信息
        
        :return: 下载任务列表，每个任务包含名称、进度、状态等信息
        """
        self.last_error = None
        if not self.connect():
            if not self.last_error:
                self.last_error = "Transmission未连接，无法获取下载列表"
            return []
            
        try:
            torrents = self.client.get_torrents()
            return [self._format_torrent_info(torrent) for torrent in torrents]
            
        except TransmissionError as e:
            self.last_error = f"获取下载列表失败: {str(e)}"
        except Exception as e:
            self.last_error = f"获取下载列表时发生未知错误: {str(e)}"
            
        return []
    
    def add_torrent(self, torrent_content, save_path=None, start_paused=False):
        """
        添加种子到下载队列
        
        :param torrent_content: 种子内容（可以是URL、磁力链接或Base64编码的种子数据）
        :param save_path: 可选，保存路径
        :param start_paused: 可选，是否添加后暂停下载，默认为False
        :return: 添加成功返回True，否则返回False
        """
        self.last_error = None
        if not self.connect():
            if not self.last_error:
                self.last_error = "Transmission未连接，无法添加下载"
            return False
            
        try:
            # 构建添加种子的参数
            kwargs = {}
            if save_path:
                kwargs['download_dir'] = save_path
            kwargs['paused'] = start_paused
            
            self.client.add_torrent(torrent_content, **kwargs)
            return True
        except TransmissionError as e:
            self.last_error = f"添加种子失败: {str(e)}"
        except Exception as e:
            self.last_error = f"添加种子时发生未知错误: {str(e)}"
            
        return False
    
    def _format_torrent_info(self, torrent):
        """
        格式化种子信息为字典
        
        :param torrent: 种子对象
        :return: 格式化后的种子信息字典，适配前端所需格式
        """
        progress = torrent.progress * 100
        
        # 状态码映射为前端需要的英文状态字符串
        status_map = {
            0: 'stopped',  # 停止
            1: 'waiting',  # 等待检查
            2: 'checking',  # 检查中
            3: 'waiting',  # 等待下载
            4: 'downloading',  # 下载中
            5: 'waiting',  # 等待上传
            6: 'seeding',  # 上传中
            7: 'seeding_wait',  # 种子排队中
            8: 'stopped'  # 已暂停
        }
        
        # 获取英文状态字符串
        status = status_map.get(torrent.status, 'unknown')
        # 获取中文状态描述
        status_text = self._get_status_text(torrent.status)
        
        return {
            'id': torrent.id,
            'name': torrent.name,
            'progress': progress,
            'status': status,  # 前端需要的英文状态
            'status_text': status_text,  # 中文状态描述
            'total_size': torrent.total_size,  # 前端期望的字段名
            'size_when_done': torrent.size_when_done,
            'downloaded': torrent.size_when_done * torrent.progress,
            'rate_download': torrent.rate_download,
            'rate_upload': torrent.rate_upload,
            'uploaded_ever': torrent.uploaded_ever,
            'save_path': torrent.download_dir,
            'type': 'download'
        }
    
    @classmethod
    def _get_status_text(cls, status_code):
        """
        将状态码转换为文本描述
        
        :param status_code: 状态码
        :return: 状态文本描述
        """
        return cls._STATUS_MAP.get(status_code, f'未知({status_code})')
    